import { Heap } from "@/utils/struct/Heap"
import { onMounted } from "@vue/runtime-core";
import * as d3 from "d3";
import { Ref, ref } from "vue";
import useD3Draw from "./useD3Draw";

export interface IElement {
    v: number;
    id: number;
}

const containerHeight = 700;
const containerWidth = 1000;
const minCompareTo = (a: IElement, b: IElement) => a.v-b.v;
const maxCompareTo = (a: IElement, b: IElement) => b.v-a.v;

const useD3Heap = (containerID: string, data: number[], isMax: boolean = false) => {
    
    const heap = new Heap<IElement>(data.map<IElement>((v, id) => { return { v, id}}), 
                                    isMax? maxCompareTo: minCompareTo);
    let d3Container, size = data.length;

    const { drawTreeMap, change, removeAndChange, insertNode } = useD3Draw(containerID, containerHeight, containerWidth);
    const removeLoading = ref<boolean>(false);
    const insertLoading = ref<boolean>(false);

    onMounted(() => {
        d3Container = d3.select('#'+containerID);
        d3Container.attr('height', containerHeight);
        d3Container.attr('width', containerWidth);
        drawTreeMap(heap.data())
        // 清除事件队列
        heap.getEventList();
    })

    const insert = (v: number) => {
        // 应该有判断是否增加深度
        if ( insertLoading.value === false ) {
            insertLoading.value = true;
            heap.insert({ v, id: size++ });
            runEventList(heap.getEventList(), insertLoading);
        }
    }
    const getReduceDimension = (index: number): [number, number] => {
        let line = 0, line_index = 0, next = 0, temp = 1;
        while ( next + temp <= index ) {
            next += temp;
            temp *= 2;
            ++line;
        }
        line_index = index - next;
        return [line, line_index];
    }
    const remove = () => {
        if ( removeLoading.value === false ) {
            removeLoading.value = true;
            const res =  heap.delete();
            runEventList(heap.getEventList(), removeLoading);
            return res;
        }
    }

    const runEventList = (eventList: any[], loading: Ref<boolean>) => {
                    
        let time = 0, a_line: number, a_index: number, b_line: number, b_index: number;
        const interval = setInterval(() => {
            if ( time >= eventList.length ) {
                clearInterval(interval)
                loading.value = false;
            } else {
                 if (eventList[time].type === 'change') {
                    [a_line, a_index] = getReduceDimension(eventList[time].index); 
                    [b_line, b_index] = getReduceDimension(eventList[time].from);
                    // console.log('change', a_line, a_index, b_line, b_index);
                    change(a_line, a_index, b_line, b_index);
                } else if ( eventList[time].type === 'delete' ) {
                    // 处理delete
                    [a_line, a_index] = getReduceDimension(heap.size());
                    removeAndChange(a_line, a_index);
                } else if ( eventList[time].type === 'insert' ) {
                    [a_line, a_index] = getReduceDimension(eventList[time].index);
                    insertNode(a_line, a_index, eventList[time].item);
                }
                ++time;
            }
        }, 1300)
    }

    return {
        heapMethods: {
            insert,
            remove,
        },
        insertLoading,
        removeLoading,
    }
}

export default useD3Heap;